﻿using ChessTest.Chess.Items;
using org.xisoft.game.utils.game;
using System;
using System.Collections.Generic;
using System.Threading;

namespace ChessTest.Chess.Algorithms
{
    /// <summary>
    /// 多线程算法
    /// </summary>
    public class MulThreadAlgorithm2<Algorithm> : AiAlgorithm
        where Algorithm : AiAlgorithm
    {

        public override MoveAction Search(AiChessboard aiChessboard, int depth)
        {

            MoveAction bestChildstep = null;
            Object obj = new object();
            Action<MoveAction> action = step =>
            {
                if (step == null) return;
                lock (obj)
                {
                    if (bestChildstep == null || bestChildstep.Score < step.Score || (bestChildstep.Score == step.Score && (bestChildstep.OldChessman == null && step.OldChessman != null)))
                    {
                        bestChildstep = step;
                        if (step.CurrentChessman != null)
                            bestChildstep.CurrentChessman = aiChessboard.GetChessman(step.FromX, step.FromY);
                        if (step.OldChessman != null)
                            bestChildstep.OldChessman = aiChessboard.GetChessman(step.ToX, step.ToY);

                    }
                }
            };


                List<SearchTask> searchTaskList = new List<SearchTask>();
                foreach (MoveAction moveAction in GetAllCanMoves(aiChessboard))
                {
                    AiChessboard newChessboard = (AiChessboard)aiChessboard.Clone();
                    moveAction.CurrentChessman = newChessboard.GetChessman(moveAction.FromX, moveAction.FromY);

                    moveAction.OldChessman = newChessboard.GetChessman(moveAction.ToX, moveAction.ToY);


                    SearchTask task = new SearchTask(newChessboard, depth, moveAction, action);
                    searchTaskList.Add(task);
                    task.Start();

                }

                foreach (SearchTask task in searchTaskList)
                    task.WaitForComplete();


            
            return bestChildstep;
        }







        class SearchTask
        {
            private readonly Action<MoveAction> action;
            private readonly AiChessboard aiChessboard;
            private readonly int depth;
            private readonly MoveAction moveAction;
            private Type algorithmType;
            public SearchTask(AiChessboard aiChessboard, int depth, MoveAction moveAction, Action<MoveAction> action)
            {
                this.action = action;
                this.aiChessboard = aiChessboard;
                this.depth = depth;
                this.moveAction = moveAction;

                algorithmType = typeof(Algorithm);
            }


            private CountdownEvent countdownEvent = new CountdownEvent(1);
            public void Start()
            {
                //Program.threadExecute.Execute(Run);

            }

            public void Run()
            {


                Chessman man = moveAction.OldChessman as Chessman;

                aiChessboard.Move(moveAction.CurrentChessman as Chessman, moveAction.ToX, moveAction.ToY);

                MoveAction step = Search(aiChessboard, depth - 1);


                moveAction.Score -= step.Score;

                action(moveAction);
                countdownEvent.Signal();
            }

            public void WaitForComplete()
            {
                countdownEvent.Wait();
                countdownEvent.Dispose();
            }

            protected MoveAction Search(AiChessboard aiChessboard, int depth)
            {

                Algorithm al = Activator.CreateInstance(algorithmType, aiChessboard) as Algorithm;


                return al.Search(aiChessboard, depth);
            }
        }
    }
}
